#pragma once

class EffectSetting;
class Setting;
class MagicItemGenerator;
#include "API/Magic/EffectItem.h"

#define DEFF EffectSetting::LookupByCode(Swap32('FIDG'))

class EffectItemGenerator {
public:
	bool onSelf;
	UInt8 noDurPct;
	UInt8 noAoEPct;
	UInt8 minMag;
	UInt8 minDur;
	UInt8 minAoE;
	UInt8 effProp;
	UInt8 actorVal;
	EffectSetting* mgef;

	struct ScriptEffectInfoGenerator : public EffectItem::ScriptEffectInfo {
		bool noMag, noDur, noAoE;
		float baseCost, barterFactor, enchantFactor;

		ScriptEffectInfoGenerator()
			: noMag(true)
			, noDur(false)
			, noAoE(false)
			, baseCost(1)
			, barterFactor(1)
			, enchantFactor(1)
		{}
	};
	ScriptEffectInfoGenerator* seff;

	MagicItemGenerator* mig;

//	static const UInt8 saveSize = 2*sizeof(bool)+5*sizeof(UInt8)+sizeof(UInt32);

	EffectItemGenerator(EffectSetting* selMgef = DEFF, int selMinMag = 0, int selMinDur = 0, int selMinAoE = 0, int selEffProp = 100, int av = 0, MagicItemGenerator* selMig = NULL, ScriptEffectInfoGenerator* scriptData = NULL);
//	EffectItemGenerator(std::stringstream& saveStr);
	EffectItemGenerator(const EffectItemGenerator& copied);
	~EffectItemGenerator();

	bool operator==(const EffectItemGenerator& right) const;
	bool operator!=(const EffectItemGenerator& right) const;
	EffectItemGenerator& operator=(const EffectItemGenerator& right);

	BSStringT	GetEffectName() const;
	UInt32		GetEffectSchool() const;
	bool		IsHostile() const;
	bool		HasMagnitude() const;
	bool		HasDuration() const;
	bool		HasArea() const;
	float		GetEffectBaseCost() const;
	float		GetEffectEnchantFactor() const;
	float		GetEffectBarterFactor() const;

	bool		GetIsOnSelf() const;
	bool		SetIsOnSelf(bool new_on_self);
	UInt8		GetNoDurationChance() const;
	bool		SetNoDurationChance(UInt8 new_no_dur_pct);
	UInt8		GetNoAreaChance() const;
	bool		SetNoAreaChance(UInt8 new_no_aoe_pct);
	UInt8		GetMinimumMagnitude() const;
	bool		SetMinimumMagnitude(UInt8 new_min_mag);
	UInt8		GetMinimumDuration() const;
	bool		SetMinimumDuration(UInt8 new_min_dur);
	UInt8		GetMinimumArea() const;
	bool		SetMinimumArea(UInt8 new_min_aoe);
	UInt8		GetEffectProportion() const;
	bool		SetEffectProportion(UInt8 new_eff_prop);
	UInt8		GetActorValue() const;
	bool		SetActorValue(UInt8 new_actor_val);

	UInt32		GetMagicEffect() const;
	bool		SetMagicEffect(EffectSetting* new_mgef);

	UInt32		GetScriptEffectScript() const;
	bool		SetScriptEffectScript(UInt32 new_script_form_id);
	BSStringT	GetScriptEffectName() const;
	bool		SetScriptEffectName(const BSStringT& new_seff_name);
	UInt32		GetScriptEffectSchool() const;
	bool		SetScriptEffectSchool(UInt32 new_seff_school);
	UInt32		GetScriptEffectVisuals() const;
	bool		SetScriptEffectVisuals(UInt32 new_seff_vis);
	bool		GetScriptEffectIsHostile() const;
	bool		SetScriptEffectIsHostile(bool new_seff_hostile);
	bool		GetScriptEffectHasMagnitude() const;
	bool		SetScriptEffectHasMagnitude(bool new_seff_has_mag);
	bool		GetScriptEffectHasDuration() const;
	bool		SetScriptEffectHasDuration(bool new_seff_has_dur);
	bool		GetScriptEffectHasArea() const { return false; }
	bool		SetScriptEffectHasArea(bool new_seff_has_aoe) { return false; }
	float		GetScriptEffectBaseCost() const;
	bool		SetScriptEffectBaseCost(float new_seff_base_cost);
	float		GetScriptEffectEnchantFactor() const;
	bool		SetScriptEffectEnchantFactor(float new_seff_ench);
	float		GetScriptEffectBarterFactor() const;
	bool		SetScriptEffectBarterFactor(float new_seff_barter);

#ifdef OBLIVION
	// Game executable code: dynamic effectitem generation
	
	bool		DetermineMagDurAoEPct(double& magPct, double& durPct, double& aoePct) const;
	bool		DetermineMagDurAoE(EffectItem* ei, UInt32 cost, double& magPct, double& durPct, double& aoePct) const;

	UInt16		GenerateEffectItem(EffectItem*& ei, UInt8 soul, Magic::RangeTypes range) const;
//	static NiTList<EffectItem*> GeneratedList;

	static Setting*	fMagicDurMagBaseCostMult;
	static Setting* fMagicCostScale;
	static Setting* fMagicAreaBaseCostMult;
	static Setting* fMagicRangeTargetCostMult;

	static Setting* fMagickaReturnBase;
	static Setting* fMagickaReturnMult;

//	std::string getSaveString() const;
//	void loadSaveString(std::stringstream& saveStr);

#else // #ifndef OBLIVION
	// CS dialog management

	static EffectItemGenerator* currPtr;

	void SetInDialog(HWND hwndDlg);
	void SetInListview(HWND dialogHandle, LRESULT sel, UINT dlgItem);

	static UInt8 SetEffectSettingInDialog(HWND hwndDlg, EffectSetting* newMGEF);

	_LOCAL static INT_PTR CALLBACK	DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);

#endif
};
